/**
 * 
 */
package au.edu.swin.videoshop.ejb.bean;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import au.edu.swin.videoshop.bean.Customer;
import au.edu.swin.videoshop.bean.Rental;
import au.edu.swin.videoshop.bean.RentalStatus;
import au.edu.swin.videoshop.bean.Staff;
import au.edu.swin.videoshop.bean.TitleCopy;
import au.edu.swin.videoshop.persistence.RentalEntity;
import au.edu.swin.videoshop.service.MiscUtil;
import au.edu.swin.videoshop.service.RentalService;

/**
 * @author julie
 *
 */
@Stateless
public class RentalServiceBean implements RentalService {

	@PersistenceContext
	private EntityManager em;
	
	/* (non-Javadoc)
	 * @see au.edu.swin.videoshop.service.RentalService#makeRental(au.edu.swin.videoshop.bean.Customer, au.edu.swin.videoshop.bean.TitleCopy, au.edu.swin.videoshop.bean.Staff, java.util.Date)
	 */
	public Rental makeRental(Customer customer, TitleCopy titleCopy, Staff staff, Date rentalDate) {
		if (titleCopy.getStore().equals(staff.getStore())) {
			if (findRentalByTitleCopyId(titleCopy.getTitleCopyId(), new Date()) == null) {
				Rental rental = new Rental();
		
				rental.setCustomer(customer);
				rental.setTitleCopy(titleCopy);
				rental.setStaff(staff);
				rental.setRentalDate(rentalDate);
				Calendar cal = Calendar.getInstance();
				cal.setTime(rentalDate);
				cal.add(Calendar.DATE, rental.getTitleCopy().getMedium().getMaxRentalPeriod());
				rental.setDueDate(cal.getTime());
				
				//Calculate first charge
				rental.setFirstCharge(titleCopy.getMedium().getRentalRate().multiply(new BigDecimal(titleCopy.getMedium().getMaxRentalPeriod())));
				
				
				rental.setStatus(RentalStatus.OPEN);
				
				return rental;
			}
		}
		
		return null;
	}
	
	/* (non-Javadoc)
	 * @see au.edu.swin.videoshop.service.RentalService#addRental(au.edu.swin.videoshop.bean.Rental)
	 */
	public void addRental(Rental rental) {
		TransferService service = new TransferService();
		RentalEntity rentalEntity = service.toRentalEntity(rental);
		em.persist(rentalEntity);
	}

	/* (non-Javadoc)
	 * @see au.edu.swin.videoshop.service.RentalService#addReturn(long, java.util.Date)
	 */
	public void addReturn(long rentalId, Date returnDate) {
		RentalEntity rentalEntity = em.find(RentalEntity.class, rentalId);
		if (rentalEntity != null) {
			rentalEntity.setStatus(RentalStatus.RETURNED.getName());
			rentalEntity.setReturnDate(returnDate);
			calculateRental(rentalEntity, returnDate);
			em.persist(rentalEntity);
		}
	}
	
	private void calculateRental(RentalEntity rentalEntity, Date returnDate) {
		//Calculate final charge
		int daysLate = MiscUtil.days(rentalEntity.getDueDate(), returnDate);
		if (daysLate > 0) {
			rentalEntity.setFinalCharge(rentalEntity.getTitleCopy().getMedium().getPenaltyRate().multiply(new BigDecimal(daysLate)));
		}
		else {
			rentalEntity.setFinalCharge(BigDecimal.ZERO);
		}
	}

	/* (non-Javadoc)
	 * @see au.edu.swin.videoshop.service.RentalService#findRentalByTitleCopyId(java.lang.String, java.util.Date)
	 */
	public Rental findRentalByTitleCopyId(String titleCopyId, Date returnDate) {
		Query query = em.createNamedQuery("findRentalByTitleCopyId");
		query.setParameter("titleCopyId", titleCopyId);
		List entityList = query.getResultList();
		
		//Find the correct one
		RentalEntity found = null;
		for (Iterator i = entityList.iterator(); i.hasNext();) {
			RentalEntity rentalEntity = (RentalEntity) i.next();
			
			if (rentalEntity.getStatus().equals(RentalStatus.OPEN.getName())) {
				if (found == null) {
					found = rentalEntity;
					break;
				}
			}
		}
		
		if (found != null) {
			calculateRental(found, returnDate);
			
			TransferService service = new TransferService();
			return service.toRentalTransferObject(found);
		}
		return null;
	}
	
	/* (non-Javadoc)
	 * @see au.edu.swin.videoshop.service.RentalService#findAllRentals()
	 */
	public List<Rental> findAllRentals() {
		Query query = em.createNamedQuery("findAllRentals");
		List entityList = query.getResultList();
		TransferService service = new TransferService();
		return service.toRentalTransferObjectList(entityList);
	}

	/* (non-Javadoc)
	 * @see au.edu.swin.videoshop.service.RentalService#findRentalsByCustomerId(long)
	 */
	public List<Rental> findRentalsByCustomerId(long customerId) {
		Query query = em.createNamedQuery("findRentalsByCustomerId");
		query.setParameter("customerId", customerId);
		List entityList = query.getResultList();
		TransferService service = new TransferService();
		return service.toRentalTransferObjectList(entityList);
	}

	/* (non-Javadoc)
	 * @see au.edu.swin.videoshop.service.RentalService#findRentalsByStaffId(long)
	 */
	public List<Rental> findRentalsByStaffId(long staffId) {
		Query query = em.createNamedQuery("findRentalsByStaffId");
		query.setParameter("staffId", staffId);
		List entityList = query.getResultList();
		TransferService service = new TransferService();
		return service.toRentalTransferObjectList(entityList);
	}

	/* (non-Javadoc)
	 * @see au.edu.swin.videoshop.service.RentalService#findRentalsByStoreId(long)
	 */
	public List<Rental> findRentalsByStoreId(long storeId) {
		Query query = em.createNamedQuery("findRentalsByStoreId");
		query.setParameter("storeId", storeId);
		List entityList = query.getResultList();
		TransferService service = new TransferService();
		return service.toRentalTransferObjectList(entityList);
	}

	/* (non-Javadoc)
	 * @see au.edu.swin.videoshop.service.RentalService#findRentalsByTitleId(long)
	 */
	public List<Rental> findRentalsByTitleId(long titleId) {
		Query query = em.createNamedQuery("findRentalsByTitleId");
		query.setParameter("titleId", titleId);
		List entityList = query.getResultList();
		TransferService service = new TransferService();
		return service.toRentalTransferObjectList(entityList);
	}

	/* (non-Javadoc)
	 * @see au.edu.swin.videoshop.service.RentalService#findRentalsByStatus(au.edu.swin.videoshop.bean.RentalStatus)
	 */
	public List<Rental> findRentalsByStatus(RentalStatus status) {
		Query query = em.createNamedQuery("findRentalsByStatus");
		query.setParameter("status", status.getName());
		List entityList = query.getResultList();
		TransferService service = new TransferService();
		return service.toRentalTransferObjectList(entityList);
	}

	/* (non-Javadoc)
	 * @see au.edu.swin.videoshop.service.RentalService#findRentalsByRentalDate(java.util.Date, java.util.Date)
	 */
	public List<Rental> findRentalsByRentalDate(Date from, Date to) {
		Query query = em.createNamedQuery("findAllRentals");
		List entityList = query.getResultList();
		List resultList = new ArrayList();
		for (Iterator i = entityList.iterator(); i.hasNext();) {
			RentalEntity rentalEntity = (RentalEntity) i.next();
			
			if (rentalEntity.getRentalDate().getTime() >= from.getTime() &&
				rentalEntity.getRentalDate().getTime() <= to.getTime()) {
				resultList.add(rentalEntity);
			}
			
		}
		TransferService service = new TransferService();
		return service.toRentalTransferObjectList(resultList);
	}
}
